
.clearfix() {
	&:before,
	&:after {
		content: " "; // 1
		display: table; // 2
	}
	&:after {
		clear: both;
	}
}


.text-overflow() {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.text-overflow-rows( @rows: 2 ) {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
	text-overflow: ellipsis;
}

.flexbox( @flex-flow: row; @justify-content: flex-start ) {
	display: flex;
	flex-flow: @flex-flow;
	justify-content: @justify-content;

	> * {
		flex-grow: 0;
		flex-shrink: 0;
	}
}


.btn-color( @background ) {
	.apply-rules( @background ) {
		.theme-color-and-background( @theme-button-color, @background );
		border-color: mix( @theme-button-shading-color, @background, @theme-button-border-color );

		&:not(:disabled):hover {
			background: mix( @theme-button-shading-color, @background, @theme-button-background-hover );
			border-color: mix( @theme-button-shading-color, @background, @theme-button-border-color-hover );

			&:active {
				background: mix( @theme-button-shading-color, @background, @theme-button-background-active );
				border-color: mix( @theme-button-shading-color, @background, @theme-button-border-color-active );
			}
		}
	}

	.apply-btn-color( @background ) when ( isString( @background ) ) {
		.theme({
			.apply-rules( @@background );
		});
	}

	.apply-btn-color( @background ) when ( default() ) {
		.theme({
			.apply-rules( @background );
		});
	}

	.apply-btn-color( @background );
}


.block-aspect-ratio( @ratio: 1 ) {
	&::before {
		content: "";
		display: block;
		padding-top: unit( ( 100 / @ratio ), % );
	}
}


.stream-hover( @ratio: ( 16 / 9 ); @duration: .333s ) {
	> .preview {
		position: relative;
		cursor: pointer;
		.block-aspect-ratio( @ratio );

		&::after {
			content: @fa-var-play-circle-o;
			display: block;
			position: absolute;
			width: 100%;
			top: 50%;
			z-index: 2;
			font: 6em/.025em FontAwesome;
			text-align: center;
			opacity: 0;
			transition: opacity @duration ease-out;

			.theme({
				color: @theme-streamitem-play-color;
				-webkit-text-stroke: .025em @theme-streamitem-play-stroke;
			});
		}

		&.opened::after {
			content: @fa-var-play-circle;
		}
	}

	> .preview:hover::after {
		opacity: 1;
	}
}


/**
 * Create media queries for dynamically scaling lists
 */
.dynamic-elems-per-row( @min, @container, @spacing, @additional ) {
	// The maximum number of elements in a row is 7
	// At 100% DPI scaling this limit will be reached at the following window widths:
	// - ".stream-item-component": 1920px (maximized window at 1920x1080)
	// - ".game-item-component": 1498px
	// All items will scale infinitely beyond that point (unscaled QHD, UHD, etc.)
	@max: 7;


	@sp: unit( ( @spacing / 100 ) );
	// width of all elements in a row combined (percentage)
	@content: ( 100% - @spacing );
	// desired element width (pixels)
	@desired: ( ( 1 - @sp ) * @container / @min );


	.loop( @i ) when ( @i =< @max ) {
		// window min-width calculation (pixels):
		// additional width to the content container element
		// plus the width of all elements including the free space between each one (row width)
		@min-width:  ceil( ( @additional +   @i       * @desired * ( 1 + @sp ) ) );
		@max-width: floor( ( @additional + ( @i + 1 ) * @desired * ( 1 + @sp ) ) );

		.rules() {
			width: ( @content / @i );
			margin-right: ( @spacing / ( @i - 1 ) );

			// no margin-right for the last element of each row
			@nth: ~"@{i}n";
			&:nth-of-type( @{nth} ) { margin-right: 0; }
		}

		// the first media query should only have a max-width constraint
		// also include the min-width constraint, so the InfiniteScrollMixin can match the query
		.mediaquery() when ( @i = @min ) {
			@media ( min-width: 1px ) and ( max-width: @max-width ) {
				.rules();
			}
		}

		// max-width constraint required, so the nth-child rule doesn't get used by other queries
		.mediaquery() when ( @i > @min ) and ( @i < @max ) {
			@media ( min-width: @min-width ) and ( max-width: @max-width ) {
				.rules();
			}
		}

		// no max-width constraint on the last media query, so the items can scale from that point
		.mediaquery() when ( @i = @max ) {
			@media ( min-width: @min-width ) {
				.rules();
			}
		}

		.mediaquery();

		.loop( ( @i + 1 ) );
	}

	// for @i=@min to 8 do...
	.loop( @min );
}
